package com.yx.cloud.map;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.aaa.lib.map.LayerManager;
import com.aaa.lib.map.MapUtils;
import com.aaa.lib.map.MapView;
import com.aaa.lib.map.layer.BaseLayer;
import com.yx.cloud.R;
import com.yx.cloud.map.callback.PowerCoveredCallback;
import com.yx.cloud.map.layer.INXNIAreaDivideLineLayer;
import com.yx.cloud.map.layer.YXAreaDivideLineLayer;
import com.yx.cloud.map.layer.YXAreaLayer;
import com.yx.cloud.map.layer.YXCleanAreaLayer;
import com.yx.cloud.map.layer.YXCustomMapLayer;
import com.yx.cloud.map.layer.YXCustomPathLayer;
import com.yx.cloud.map.layer.YXForbiddenAreaLayer;
import com.yx.cloud.map.layer.YXForbiddenLineLayer;
import com.yx.cloud.map.layer.YXForbiddenMopAreaLayer;
import com.yx.cloud.map.layer.YXImageMarkerLayer;
import com.yx.cloud.map.layer.YXMoveableImageMarkerLayer;
import com.yx.cloud.map.layer.YXObjectRecognitionLayer;
import com.yx.cloud.map.layer.YXPowerLayer;
import com.yx.cloud.map.layer.YXRoomTagLayer;
import com.yx.cloud.map.layer.YXSweeperLayer;
import com.iot.product.sweeper.bean.AreaInfo;
import com.iot.product.sweeper.bean.Map;
import com.iot.product.sweeper.bean.MapInfo;
import com.iot.product.sweeper.bean.ObjectRecognition;
import com.iot.product.sweeper.bean.Path;
import com.iot.product.sweeper.bean.Power;
import com.iot.product.sweeper.bean.Room;
import com.iot.product.sweeper.bean.Sweeper;
import com.iot.common.utils.LogUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class YXMapView extends MapView<YXLayerManager> {
    private static final String TAG = "YXMapView";
    public boolean canRotateCleanArea = true;
    protected float minCleanAreaSize = 1.0f;
    protected float powerProtectAreaSize = 0.5f;//电源保护区域 默认0.5米
    protected float max_zoom = 2f;
    protected float min_zoom = 0.5f;
    private boolean touchable = true;
    private float rotation;//地图旋转角度
    private float scale = 1f;
    private PointF tempPoint = new PointF();
    private Map map;
    //各种图层
    private YXCustomMapLayer mapLayer;
    private YXCustomPathLayer pathLayer;
    private YXSweeperLayer sweeperLayer;
    private YXPowerLayer powerLayer;
    private YXAreaDivideLineLayer areaDivideLineLayer;
    private YXMoveableImageMarkerLayer selectPointLayer;
    private List<YXAreaLayer> tempAreaLayers;

    private volatile boolean isUserOperated = false; //如果用户缩放平移地图后 就保持这个缩放偏移 不再自动居中
    private boolean isForbiddenAreaChange = false;  //用于记录图层是否新增或者移除
    //图层是否可见 由于一个界面可能出现多个地图, 不同地图图层可见不同
    private boolean mapVisible = true;
    private boolean pathVisible = true;
    private boolean roomTagVisible = true;
    private boolean forbiddenAreaVisible = true;
    private boolean forbiddenLineVisible = true;
    private boolean forbiddenMopVisible = true;
    private boolean cleanAreaVisible = true;
    private boolean powerVisible = true;
    private boolean sweeperVisible = true;
    private boolean selectPointVisible = false;
    private float baseScale = 1;
    private boolean canSelectRoom = false;

    private boolean canMultiSelectRoom = false;
    private boolean showRoomOrder = false;
    private boolean showCustom = false;
    private boolean showSuction = false;
    private boolean showWater = false;
    private boolean showCleanTimes = false;
    private boolean showProtectArea = false;
    private RoomSelectCallback selectCallback;
    private PowerCoveredCallback powerCoveredCallback;
    private ForbiddenAreaChangeCallback forbiddenAreaChangeCallback;
    private LayerManager.LayerListChangeListener layerListChangeListener = new LayerManager.LayerListChangeListener() {
        @Override
        public void onLayerAdd(BaseLayer layer) {
            LogUtils.i("onLayerAdd" + layer.getClass().getSimpleName());
            //            refresh();
        }

        @Override
        public void onLayerRemove(BaseLayer layer) {
            LogUtils.i("onLayerRemove" + layer.getClass().getSimpleName());
            if (tempAreaLayers.contains(layer)) {
                //临时区域列表中移除它
                tempAreaLayers.remove(layer);
            }

            //有区域被移除 同类型区域中 序号大于此区域的全部减一
            if (layer instanceof YXCleanAreaLayer) {
                List cleanAreaLayers = mLayerManager.getLayerByType(YXCleanAreaLayer.class);
                reorder(cleanAreaLayers, ((YXCleanAreaLayer) layer).getOrder());
            }

            //有区域被移除 同类型区域中 序号大于此区域的全部减一
            if (layer instanceof YXForbiddenAreaLayer) {
                List cleanAreaLayers = mLayerManager.getLayerByType(YXForbiddenAreaLayer.class);
                reorder(cleanAreaLayers, ((YXForbiddenAreaLayer) layer).getOrder());
                cleanAreaLayers = mLayerManager.getLayerByType(YXForbiddenMopAreaLayer.class);
                reorder(cleanAreaLayers, ((YXForbiddenAreaLayer) layer).getOrder());
            }

            refresh();
        }
    };

    public YXMapView(Context context) {
        this(context, null);
    }

    public YXMapView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public YXMapView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setZoomLimit(1f, 32f);//缩放还需调整 设置成2-16 多地图显示怪异
        mLayerManager = new YXLayerManager(this);
        mLayerManager.setLayerListChangeListener(layerListChangeListener);
        tempAreaLayers = new ArrayList<>();

        map = new Map();
    }


    public void setTouchable(boolean touchable) {
        this.touchable = touchable;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        loadMapOffsetAndScale();
        refresh();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //判断是否可以操作
        if (!touchable) {
            return false;
        } else {
            return super.onTouchEvent(event);
        }

    }

    public void initMap(Map map) {
        this.map = map;
        LogUtils.i("initMap----------------");
        refreshMapLayer(map.getMap());
        refreshPathLayer(map.getPath());
        refreshAreaLayer(map.getArea());
        refreshPowerLayer(map.getPower());
        refreshDeviceLayer(map.getSweeper());
        refreshRoomLayer(map.getRoom());
        refreshObjectRecognitionLayer(map.getObjectList());
//        addTestObjectRecognition();
        refresh();
    }

    private void addTestObjectRecognition() {
        List<ObjectRecognition> objectRecognitionList = new ArrayList<>();
        ObjectRecognition obj1 = ObjectRecognition.newBuilder()
                .id(1)
                .name("狗屎")
                .icon(BitmapFactory.decodeResource(getResources(), R.mipmap.home_charge_invalid))
                .position(20, 20)
                .build();
        ObjectRecognition obj2 = ObjectRecognition.newBuilder()
                .id(1)
                .name("holy")
                .icon(BitmapFactory.decodeResource(getResources(), R.mipmap.area_delete))
                .position(120, 120)
                .build();
        ObjectRecognition obj3 = ObjectRecognition.newBuilder()
                .id(1)
                .name("shit")
                .icon(BitmapFactory.decodeResource(getResources(), R.mipmap.add_icon))
                .position(220, 220)
                .build();
        objectRecognitionList.add(obj1);
        objectRecognitionList.add(obj2);
        objectRecognitionList.add(obj3);
        refreshObjectRecognitionLayer(objectRecognitionList);

    }

    public void rotate(float angle) {
        if (mapLayer != null && mapLayer.getMapBitmap() != null) {
            rotation = rotation + angle;
            int[] clipRect = mapLayer.getClipRect();
            float clipRectCenterX = (clipRect[0] + clipRect[2]) / 2f;
            float clipRectCenterY = (clipRect[1] + clipRect[3]) / 2f;
            PointF pointF = MapUtils.getTransformedPoint(mMatrix, clipRectCenterX, clipRectCenterY);
            isUserOperated = true;
            super.rotate(angle, pointF.x, pointF.y);
        }
    }

    @Override
    public void scale(float scale, float centerX, float centerY) {
        if (mapLayer != null && mapLayer.getMapBitmap() != null) {
            float targetZoom = this.scale * scale;
            float limitedScale = scale;
            if (targetZoom > max_zoom) {
                limitedScale = max_zoom / this.scale;
                targetZoom = max_zoom;
            } else if (targetZoom < min_zoom) {
                limitedScale = min_zoom / this.scale;
                targetZoom = min_zoom;
            }
            this.scale = targetZoom;

            isUserOperated = true;
            super.scale(limitedScale, centerX, centerY);
        }
    }

    @Override
    public void translate(float distanceX, float distanceY) {
        //限制滑动范围
        if (mapLayer != null && mapLayer.getMapBitmap() != null) {
            float viewCenterX = getWidth() / 2;
            float viewCenterY = getHeight() / 2;
            MapUtils.getInverseRotatedPoint(getTransform(), distanceX, distanceY, tempPoint);
            MapUtils.getTransformedPoint(getTransform(), map.getMap().width / 2, map.getMap().height / 2, tempPoint);
            double currentDistance = MapUtils.distance(viewCenterX, viewCenterY, tempPoint.x, tempPoint.y);
            double border = Math.max(map.getMap().height, map.getMap().width) / 2 * scale;
            //地图中心点 -  地图边界<view大小
            if (currentDistance - border < Math.max(getHeight(), getWidth()) / 2) {
                super.translate(distanceX, distanceY);
            } else {
                double willDistance = MapUtils.distance(viewCenterX, viewCenterY, tempPoint.x + distanceX, tempPoint.y + distanceY);
                if (currentDistance >= willDistance) {
                    super.translate(distanceX, distanceY);
                }
            }
            isUserOperated = true;
        }
    }

    public void loadMapOffsetAndScale() {
        LogUtils.i("isUserOperated: " + isUserOperated + " mapLayer == null" + (mapLayer == null));
        if (mapLayer != null && mapLayer.getMapBitmap() != null) {
            int mapWidth = map.getMap().width;
            int mapHeight = map.getMap().height;
            int viewWidth = getWidth();
            int viewHeight = getHeight();
            LogUtils.i(" width:  " + mapWidth + " height : " + mapHeight + " map w : " + viewWidth + "  map h: " + viewHeight);
            if (mapWidth != 0 && mapHeight != 0 && viewWidth != 0 && viewHeight != 0) {
                //计算地图大小 计算地图可缩放比例
                baseScale = calculateScaleFactor(mapWidth, mapHeight, viewWidth, viewHeight);
                setZoomLimit(baseScale * 8 / 10, baseScale * 4);
                LogUtils.i(" min zoom : " + min_zoom + " max zoom :" + max_zoom);
                if (!isUserOperated) {
                    getTransform().reset();

                    float mapCenterX = mapWidth / 2f;
                    float mapCenterY = mapHeight / 2f;

                    //裁剪中心移动到（0，0） 得到向量
                    int[] clipRect = mapLayer.getClipRect();
                    //裁剪中心 裁剪中心= (起始位置+结束位置+1)/2
                    float clipRectCenterX = (clipRect[0] + clipRect[2] + 1) / 2f;
                    float clipRectCenterY = (clipRect[1] + clipRect[3] + 1) / 2f;
                    super.translate(0 - clipRectCenterX, 0 - clipRectCenterY);
                    LogUtils.i(" clip offset : " + (clipRectCenterX - mapCenterX) + " " + (clipRectCenterY - mapCenterY));

                    //缩放到屏幕大小
                    this.scale = 1f;
                    scale(baseScale, 0, 0);

                    //中心从（0,0）平移到界面中心  用视图中心-地图中心 得到向量
                    float offsetX = viewWidth / 2;
                    float offsetY = viewHeight / 2;
                    super.translate(offsetX, offsetY);
                    LogUtils.i("map offset x  : " + offsetX + " y " + offsetY + " scale : " + baseScale);

                    //旋转
                    PointF pointF = MapUtils.getTransformedPoint(getTransform(), clipRectCenterX, clipRectCenterY);
                    rotate(rotation, pointF.x, pointF.y);

                    isUserOperated = false;
                    refresh();
                }
            }
        }
    }

    private float calculateScaleFactor(int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight) {
        float scaleWidth = (float) viewWidth / (float) bitmapWidth;
        float scaleHeight = (float) viewHeight / (float) bitmapHeight;
        float scale = Math.min(scaleWidth, scaleHeight);
        return scale * 0.8f;
    }

    public void clearLayerFocus() {
        YXAreaLayer.clearFocus();
        refresh();
    }

    private void refreshMapLayer(MapInfo map) {
        if (mapLayer == null) {
            //添加地图
            mapLayer = new YXCustomMapLayer(this);
            mapLayer.setVisible(mapVisible);
            mLayerManager.addLayer(mapLayer);
        }

        mapLayer.setMapBean(map);
        loadMapOffsetAndScale();

    }

    public void resetOffsetAndScale() {
        isUserOperated = false;
    }

    public void refreshPathLayer(Path path) {
        if (pathLayer == null) {
            //添加路径
            pathLayer = new YXCustomPathLayer(this);
            pathLayer.setVisible(pathVisible);
            mLayerManager.addLayer(pathLayer);
        }

        pathLayer.setPath(map.getMap(), path);
        refresh();
    }

    public void refreshAreaLayer(List<AreaInfo> areaList) {
        map.setArea(areaList);
        if (YXCleanAreaLayer.isCleanAreaEditable) {
            //如果在编辑划区 就不刷新区域
            return;
        }

        //重新赋值 避免多线程操作
        List<AreaInfo> tempList = new ArrayList<>();
        tempList.addAll(areaList);

        //移除所有区域图层
        List<BaseLayer> newAreaLayerList = new ArrayList<>();
        int forbiddenAreaCount = 0;  //禁区编号从0开始
        int cleanAreaOrder = 0;  //禁区编号从0开始
        for (AreaInfo areaInfo : tempList) {
            //            YXAreaLayer layer = isLayerExist(areaInfo);  判断图层是否存在 如果图层不存在就新建
            YXAreaLayer layer;
            if (areaInfo.getType() == YXAreaLayer.TYPE_CLEAN_AREA) {
                layer = new YXCleanAreaLayer(this);
                layer.setVisible(cleanAreaVisible);
                layer.setOrder(cleanAreaOrder++);
            } else if (areaInfo.getType() == YXAreaLayer.TYPE_FORBIDDEN_AREA) {
                layer = new YXForbiddenAreaLayer(this);
                layer.setVisible(forbiddenAreaVisible);
                layer.setOrder(forbiddenAreaCount++);
            } else if (areaInfo.getType() == YXAreaLayer.TYPE_FORBIDDEN_LINE) {
                layer = new YXForbiddenLineLayer(this);
                layer.setVisible(forbiddenLineVisible);
            } else if (areaInfo.getType() == YXAreaLayer.TYPE_FORBIDDEN_MOP) {
                layer = new YXForbiddenMopAreaLayer(this);
                layer.setVisible(forbiddenMopVisible);
                layer.setOrder(forbiddenAreaCount++);
            } else if (areaInfo.getType() == YXAreaLayer.TYPE_ROOM) {
                continue;
            } else if (areaInfo.getType() == YXAreaLayer.TYPE_LOCATION) {
                continue;
            } else {
                continue;
            }
            layer.initAreaLayer(areaInfo);
            newAreaLayerList.add(layer);
        }
        //添加临时的图层 ， 比如新增禁区 新增划区清扫
        newAreaLayerList.addAll(tempAreaLayers);
        LogUtils.i("forbiddenAreaCount " + forbiddenAreaCount);

        mLayerManager.removeLayersByType(YXForbiddenAreaLayer.class, YXForbiddenLineLayer.class, YXForbiddenMopAreaLayer.class, YXCleanAreaLayer.class);
        mLayerManager.addLayers(newAreaLayerList);

        refresh();
    }

    public void refreshDeviceLayer(Sweeper sweeper) {
        refreshDeviceLayer((float) sweeper.x, (float) sweeper.y, (float) sweeper.rotation, sweeper.icon);
    }

    private void refreshDeviceLayer(float centerX, float centerY, float direction, Bitmap bitmap) {
        if (sweeperLayer == null) {
            //添加扫地机
            sweeperLayer = new YXSweeperLayer(this);
            sweeperLayer.setVisible(sweeperVisible);
            mLayerManager.addLayer(sweeperLayer);
        }
        //不设置方向 默认以上次的点到当前点的方向
        sweeperLayer.setMarker(centerX, centerY, direction);
        if (bitmap != null) {
            sweeperLayer.setMarkerBitmap(bitmap);
        } else {
            //不设置就不替换
        }
    }

    /**
     * 刷新物品识别列表
     */
    public void refreshObjectRecognitionLayer(List<ObjectRecognition> objectRecognitionList) {
        if (objectRecognitionList == null) {
            return;
        }

        List<BaseLayer> objectLayerList = new ArrayList<>();
        List oldObjectRecognitionLayer = mLayerManager.getLayersByType(YXObjectRecognitionLayer.class);
        //移除所有区域图层
        for (int j = 0; j < objectRecognitionList.size(); j++) {
            boolean isShowDetail = false;
            ObjectRecognition objectRecognition = objectRecognitionList.get(j);
            for (int i = 0; i < oldObjectRecognitionLayer.size(); i++) {
                YXObjectRecognitionLayer objectLayer = (YXObjectRecognitionLayer) oldObjectRecognitionLayer.get(i);
                if (objectLayer.getObjectRecognition().getId() == objectRecognition.getId()) {
                    isShowDetail = objectLayer.isShowDetail();
                    break;
                }
            }

            YXObjectRecognitionLayer objectLayer = new YXObjectRecognitionLayer(this, objectRecognition);
            setObjectIcon(objectLayer, objectRecognition);
            objectLayer.setShowDetail(isShowDetail);
            objectLayerList.add(objectLayer);
        }

        mLayerManager.removeLayersByType(YXObjectRecognitionLayer.class);
        mLayerManager.addLayers(objectLayerList);
    }

    private void setObjectIcon(YXObjectRecognitionLayer objectRecognitionLayer, ObjectRecognition objectRecognition) {
        int type = objectRecognition.getType();
        int markerId = 0;
        int iconId = 0;
        int nameId = 0;
        switch (type) {
            case ObjectRecognition.TYPE_WIRE:
                markerId = R.mipmap.marker_wire;
                iconId = R.mipmap.icon_wire;
                nameId = R.string.obj_wire;
                break;
            case ObjectRecognition.TYPE_SHOSE:
                markerId = R.mipmap.marker_shose;
                iconId = R.mipmap.icon_shose;
                nameId = R.string.obj_shoes;
                break;
            case ObjectRecognition.TYPE_SOCKS:
                markerId = R.mipmap.marker_socks;
                iconId = R.mipmap.icon_socks;
                nameId = R.string.obj_socks;
                break;
            case ObjectRecognition.TYPE_TOWELS:
                markerId = R.mipmap.marker_towels;
                iconId = R.mipmap.icon_towels;
                nameId = R.string.obj_towels;
                break;
            case ObjectRecognition.TYPE_BASE:
                markerId = R.mipmap.marker_base;
                iconId = R.mipmap.icon_base;
                nameId = R.string.obj_base;
                break;
            case ObjectRecognition.TYPE_SCALES:
                markerId = R.mipmap.marker_scales;
                iconId = R.mipmap.icon_scales;
                nameId = R.string.obj_scales;
                break;
            case ObjectRecognition.TYPE_PET_PLATE:
                markerId = R.mipmap.marker_pet_plate;
                iconId = R.mipmap.icon_pet_plate;
                nameId = R.string.obj_pet_plate;
                break;
            case ObjectRecognition.TYPE_PET_FECES:
                markerId = R.mipmap.marker_pet_feces;
                iconId = R.mipmap.icon_pet_feces;
                nameId = R.string.obj_pet_feces;
                break;
            case ObjectRecognition.TYPE_BALL:
                markerId = R.mipmap.marker_ball;
                iconId = R.mipmap.icon_ball;
                nameId = R.string.obj_ball;
                break;
            case ObjectRecognition.TYPE_BOTTLE:
                markerId = R.mipmap.marker_bottle;
                iconId = R.mipmap.icon_bottle;
                nameId = R.string.obj_bottle;
                break;
            case ObjectRecognition.TYPE_FABRIC:
                markerId = R.mipmap.marker_cloth;
                iconId = R.mipmap.icon_cloth;
                nameId = R.string.obj_fabric;
                break;
            case ObjectRecognition.TYPE_TAPE:
                markerId = R.mipmap.marker_tape;
                iconId = R.mipmap.icon_tape;
                nameId = R.string.obj_tape;
                break;
            case ObjectRecognition.TYPE_PEN:
                markerId = R.mipmap.marker_pen;
                iconId = R.mipmap.icon_pen;
                nameId = R.string.obj_pen;
                break;
            case ObjectRecognition.TYPE_TOY:
                markerId = R.mipmap.marker_toy;
                iconId = R.mipmap.icon_toy;
                nameId = R.string.obj_toy;
                break;
            default:
                //case ObjectRecognition.TYPE_OBSTACLE:
                markerId = R.mipmap.marker_obstacles;
                iconId = R.mipmap.icon_obstacles;
                nameId = R.string.obj_obstacles;
                break;
        }

        if (iconId != 0) {
            objectRecognitionLayer.setMarkerBitmap(BitmapFactory.decodeResource(getResources(), markerId));
            objectRecognitionLayer.setIcon(BitmapFactory.decodeResource(getResources(), iconId));
            objectRecognition.setName(getContext().getString(nameId));
        } else {
            objectRecognitionLayer.setMarkerBitmap(null);
            objectRecognitionLayer.setIcon(null);
            objectRecognition.setName("");
        }

    }


    /**
     * 刷新电源
     */
    public void refreshPowerLayer(Power power) {
        refreshPowerLayer((float) power.x, (float) power.y, (float) power.rotation);
    }

    private void refreshPowerLayer(float centerX, float centerY, float rotation) {
        LogUtils.i("refreshPowerLayer : " + centerX + " , " + centerY + " rotation: " + rotation);
        if (powerLayer == null) {
            //添加电源图层
            powerLayer = new YXPowerLayer(this);
            powerLayer.setVisible(powerVisible);
            powerLayer.setProtectRadiu(map.getMap().getScreenSize(powerProtectAreaSize));
            mLayerManager.addLayer(powerLayer);
        }
        powerLayer.setCenter(centerX, centerY);
        powerLayer.setRotation(rotation);
    }

    public void refreshRoomLayer1(List<Room> rooms) {
        List<BaseLayer> newRoomLayers = new ArrayList<>();
        for (Room room : rooms) {
            YXRoomTagLayer layer = new YXRoomTagLayer(this);
            layer.setVisible(roomTagVisible);
            layer.initAreaLayer(room);
            newRoomLayers.add(layer);
        }
        //移除所有房间图层
        mLayerManager.removeLayersByType(YXRoomTagLayer.class);
        //添加新的房间图层
        mLayerManager.addLayers(newRoomLayers);
        refresh();
        LogUtils.i("room size " + mLayerManager.getLayerByType(YXRoomTagLayer.class).size());
    }

    public void refreshRoomLayer(List<Room> roomBeanList) {
        if (!hasMap()) {
            return;
        }
        List<Room> newRoomList = new ArrayList<>();
        newRoomList.addAll(roomBeanList);

        //        mLayerManager.removeLayersByType(YXRoomTagLayer.class);
        List oldRoomTagLayer = mLayerManager.getLayersByType(YXRoomTagLayer.class);
        //移除所有区域图层
        List<BaseLayer> newRoomLayer = new ArrayList<>();
        for (int j = 0; j < newRoomList.size(); j++) {
            Room roomBean = newRoomList.get(j);
            boolean isSelected = false;
            //TODO由于要设置清扫顺序的原因,  这里 应当是按照roombean在数组中的位置来设置order, 但是
            int order = -1;
            for (int i = 0; i < oldRoomTagLayer.size(); i++) {
                YXRoomTagLayer roomTagLayer = (YXRoomTagLayer) oldRoomTagLayer.get(i);
                if (roomTagLayer.getAreaInfo().getId() == roomBean.getId()) {
                    isSelected = roomTagLayer.isSelected();
                    order = roomTagLayer.getOrder();
                    break;
                }
            }

            YXRoomTagLayer layer = new YXRoomTagLayer(this);
            layer.setSelected(isSelected);
            layer.initAreaLayer(roomBean);
            layer.setOrder(order);
            layer.setVisible(roomTagVisible);
            newRoomLayer.add(layer);
        }
        mLayerManager.removeLayers(oldRoomTagLayer);
        mLayerManager.addLayers(newRoomLayer);


        refresh();
    }

    /**
     * 添加区域分割线
     * 限制只能添加一个
     */
    public void addAreaDivideLineLayer() {
        if (areaDivideLineLayer == null) {
            MapInfo mapInfo = map.getMap();
            areaDivideLineLayer = new YXAreaDivideLineLayer(this);
            areaDivideLineLayer.setDividerMoveListener(new YXAreaDivideLineLayer.OnDividerMoveListener() {
                @Override
                public void onDividerMove(float x1, float y1, float x2, float y2) {
                    List<YXRoomTagLayer> selectedMergeTags = getSelectedRoomTag();
                    if (selectedMergeTags.size() == 1) {
                        List<PointF> dividePoints = YXAreaDivideLineLayer.calculateCrossPoint(mapInfo, (int) selectedMergeTags.get(0).getAreaInfo().getId(), x1, y1, x2, y2);
                        if (dividePoints.size() >= 2) {
                            areaDivideLineLayer.setCrossPoints(dividePoints.get(0), dividePoints.get(dividePoints.size() - 1));
                            return;
                        }
                    }
                    areaDivideLineLayer.setCrossPoints(null, null);
                }
            });
            //TODO 分割线未居中 需要居中到裁剪中心
            areaDivideLineLayer.setLine(mapInfo.width / 2f - 30, mapInfo.height / 2f, mapInfo.width / 2f + 30, mapInfo.height / 2f);
            mLayerManager.addLayer(areaDivideLineLayer);
            refresh();
        }
    }

    public void addInxniAreaDivideLineLayer() {
        if (areaDivideLineLayer == null) {
            MapInfo mapInfo = map.getMap();
            areaDivideLineLayer = new INXNIAreaDivideLineLayer(this);
            areaDivideLineLayer.setDividerMoveListener(new YXAreaDivideLineLayer.OnDividerMoveListener() {
                @Override
                public void onDividerMove(float x1, float y1, float x2, float y2) {
                    List<YXRoomTagLayer> selectedMergeTags = getSelectedRoomTag();
                    if (selectedMergeTags.size() == 1) {
                        List<PointF> dividePoints = YXAreaDivideLineLayer.calculateCrossPoint(mapInfo, (int) selectedMergeTags.get(0).getAreaInfo().getId(), x1, y1, x2, y2);
                        if (dividePoints.size() >= 2) {
                            areaDivideLineLayer.setCrossPoints(dividePoints.get(0), dividePoints.get(dividePoints.size() - 1));
                            return;
                        }
                    }
                    areaDivideLineLayer.setCrossPoints(null, null);
                }
            });
            YXRoomTagLayer divideLineRoom = getDivideLineRoom();
            Room room = divideLineRoom.getAreaInfo();

            //TODO 分割线未居中 需要居中到裁剪中心
            areaDivideLineLayer.setLine(room.getCenter().x - 15, room.getCenter().y, room.getCenter().x + 15, room.getCenter().y);
            mLayerManager.addLayer(areaDivideLineLayer);
            refresh();
        }
    }

    /**
     * 移除区域分割线
     */
    public void removeAreaDivideLineLayer() {
        mLayerManager.removeLayer(areaDivideLineLayer);
        areaDivideLineLayer = null;
        refresh();
    }

    public void refreshSelectPointLayer() {
        if (hasMap()) {
            int[] clipRect = mapLayer.getClipRect();
            float clipRectCenterX = (clipRect[0] + clipRect[2]) / 2f;
            float clipRectCenterY = (clipRect[1] + clipRect[3]) / 2f;
            refreshSelectPointLayer(new PointF(clipRectCenterX, clipRectCenterY));
        } else {
            LogUtils.i("no map");
        }
    }

    public void refreshSelectPointLayer(PointF pointF) {
        if (selectPointLayer == null) {
            selectPointLayer = new YXMoveableImageMarkerLayer(this);
            selectPointLayer.setVisible(selectPointVisible);
            mLayerManager.addLayer(selectPointLayer);
        }
        selectPointLayer.setMarker(pointF, 0);
        refresh();
    }

    public YXMoveableImageMarkerLayer getSelectPointLayer() {
        return selectPointLayer;
    }


    public void addTempAreaLayer(Class cls) {
        YXAreaLayer areaLayer = null;
        if (YXCleanAreaLayer.class == cls) {
            areaLayer = new YXCleanAreaLayer(this);
            areaLayer.setVisible(cleanAreaVisible);
            areaLayer.initAreaLayer();
            areaLayer.setOrder(mLayerManager.getLayerCountByType(YXCleanAreaLayer.class));//划区清扫的区域   添加时序号递增  删除时重排
        } else if (YXForbiddenAreaLayer.class == cls) {
            areaLayer = new YXForbiddenAreaLayer(this);
            areaLayer.initAreaLayer();
            areaLayer.setVisible(forbiddenAreaVisible);
            int forbidAreaCount = mLayerManager.getLayerCountByType(YXForbiddenAreaLayer.class, YXForbiddenMopAreaLayer.class);
            areaLayer.setOrder(forbidAreaCount);
        } else if (YXForbiddenMopAreaLayer.class == cls) {
            areaLayer = new YXForbiddenMopAreaLayer(this);
            areaLayer.initAreaLayer();
            areaLayer.setVisible(forbiddenMopVisible);
            int forbidAreaCount = mLayerManager.getLayerCountByType(YXForbiddenAreaLayer.class, YXForbiddenMopAreaLayer.class);
            areaLayer.setOrder(forbidAreaCount);
        } else if (YXForbiddenLineLayer.class == cls) {
            areaLayer = new YXForbiddenLineLayer(this);
            areaLayer.initAreaLayer();
            areaLayer.setVisible(forbiddenLineVisible);
        } else {
            return;
        }
        tempAreaLayers.add(areaLayer);
        mLayerManager.addLayer(areaLayer);
        refresh();
    }

    public void removeTempAreaLayer() {
        mLayerManager.removeLayers(tempAreaLayers);
        tempAreaLayers.clear();
        refresh();
    }

    public void removeLayer(BaseLayer layer) {
        mLayerManager.removeLayer(layer);
        refresh();
    }

    /**
     * 设置房间标签是否可见
     *
     * @param visible 可见性
     */
    public void setRoomTagMode(boolean visible, boolean canSelect, boolean canMultiSelect,
                               boolean showOrder, boolean showCustom, boolean showCleanTimes, boolean showWater) {

        this.showCustom = showCustom;
        this.canSelectRoom = canSelect;
        this.canMultiSelectRoom = canMultiSelect;
        this.showRoomOrder = showOrder;
        this.showSuction = true;
        this.showWater = showWater;
        this.showCleanTimes = showCleanTimes;

        //选择单选模式时 如果选中多个 就只保留一个选中
        if (!canMultiSelectRoom) {
            List<YXRoomTagLayer> roomLayers = getSelectedRoomTag();
            if (roomLayers.size() > 1) {
                for (int i = 1; i < roomLayers.size(); i++) {
                    roomLayers.get(i).setSelected(false);
                }
            }
        }

        setLayerVisible(visible, YXRoomTagLayer.class);
        refresh();
    }

    /**
     * 设置禁区是否可编辑
     *
     * @param editable 可编辑
     */
    public void setForbiddenAreaEditable(boolean editable) {
        YXForbiddenAreaLayer.isForbiddenAreaEditable = editable;
        refresh();
    }

    public void setForbiddenMopAreaEditable(boolean editable) {
        YXForbiddenMopAreaLayer.isForbiddenMopEditable = editable;
        refresh();
    }

    /**
     * 设置禁过线是否可编辑
     *
     * @param editable 可编辑
     */
    public void setForbiddenLineEditable(boolean editable) {
        YXForbiddenLineLayer.isForbiddenLineEditable = editable;
        refresh();
    }

    public boolean isCleanAreaEditable() {
        return YXCleanAreaLayer.isCleanAreaEditable;
    }

    /**
     * 设置自定义区域清扫是否可编辑
     *
     * @param editable 可编辑
     */
    public void setCleanAreaEditable(boolean editable) {
        YXCleanAreaLayer.isCleanAreaEditable = editable;
        refresh();
    }

    /**
     * 设置图层可见(可设置多个)
     * @param visible 图层是否可见
     * @param clss  不可见图层的类型
     */
    public void setLayerVisible(boolean visible, Class... clss) {
        for (Class cls : clss) {
            setVisiByType(cls, visible);
        }
        List<BaseLayer> layers = mLayerManager.getLayersByType(clss);
        for (BaseLayer layer : layers) {
            layer.setVisible(visible);
        }
        refresh();
    }

    /**
     * 根据类型设置图层是否可见
     */
    private void setVisiByType(Class cls, boolean visible) {
        if (YXCustomMapLayer.class == cls) {
            mapVisible = visible;
        } else if (YXCustomPathLayer.class == cls) {
            pathVisible = visible;
        } else if (YXForbiddenAreaLayer.class == cls) {
            forbiddenAreaVisible = visible;
        } else if (YXForbiddenLineLayer.class == cls) {
            forbiddenLineVisible = visible;
        } else if (YXForbiddenMopAreaLayer.class == cls) {
            forbiddenMopVisible = visible;
        } else if (YXCleanAreaLayer.class == cls) {
            cleanAreaVisible = visible;
        } else if (YXRoomTagLayer.class == cls) {
            roomTagVisible = visible;
        } else if (YXImageMarkerLayer.class == cls) {
            sweeperVisible = visible;
        } else if (YXPowerLayer.class == cls) {
            powerVisible = visible;
        }
    }

    /**
     * 是否显示电源保护区域
     *
     * @param show 显示/不显示
     */
    public void showPowerProtectArea(boolean show) {
        this.showProtectArea = show;
        refresh();
    }

    public boolean isShowProtectArea() {
        return showProtectArea;
    }

    public List getAreaLayerListByType(Class... cls) {
        List<BaseLayer> layers = new ArrayList<>();
        for (int i = 0; i < cls.length; i++) {
            layers.addAll(mLayerManager.getLayerByType(cls[i]));
        }
        return layers;
    }

    public int getUniqueAreaId(int type) {
        int startID = 0;
        if (type == YXAreaLayer.TYPE_CLEAN_AREA) {
            startID = 200;
            List<YXAreaLayer> cleanAreaLayers = getAreaLayerListByType(YXCleanAreaLayer.class);
            return loopToGetUniqueAreaId(cleanAreaLayers, startID);
        } else if (type == YXAreaLayer.TYPE_FORBIDDEN_AREA || type == YXAreaLayer.TYPE_FORBIDDEN_MOP) {
            startID = 300;
            List<YXAreaLayer> forbiddenAreaLayers = getAreaLayerListByType(YXForbiddenAreaLayer.class, YXForbiddenMopAreaLayer.class);
            return loopToGetUniqueAreaId(forbiddenAreaLayers, startID);
        } else if (type == YXAreaLayer.TYPE_FORBIDDEN_LINE) {
            startID = 400;
            List<YXAreaLayer> forbiddenLineLayers = getAreaLayerListByType(YXForbiddenLineLayer.class);
            return loopToGetUniqueAreaId(forbiddenLineLayers, startID);
        }
        return 0;
    }

    private int loopToGetUniqueAreaId(List<? extends YXAreaLayer> layers, int startId) {
        while (isIdExist(layers, startId)) {
            startId++;
        }
        return startId;
    }

    private boolean isIdExist(List<? extends YXAreaLayer> layers, int id) {
        for (YXAreaLayer areaLayer : layers) {
            if (id == areaLayer.getAreaInfo().getId()) {
                return true;
            }
        }
        return false;
    }

    private void reorder(List<YXAreaLayer> list, int order) {
        for (YXAreaLayer layer : list) {
            if (layer.getOrder() > order) {
                layer.setOrder(layer.getOrder() - 1);
            }
        }
    }

    /**
     * 如果是单选  每选中一个 就取消其他标签选中
     * @param select
     */
    public void handleRoomSelect(YXRoomTagLayer roomTagLayer, boolean select) {
        List roomTagLayers = mLayerManager.getLayerByType(YXRoomTagLayer.class);
        if (select) {
            long id = roomTagLayer.getAreaInfo().getId();
            if (!canMultiSelectRoom) {
                //如果是单选 就取消其他标签的选中
                for (int i = 0; i < roomTagLayers.size(); i++) {
                    YXRoomTagLayer layer = (YXRoomTagLayer) roomTagLayers.get(i);
                    if (layer.getAreaInfo().getId() != id) {
                        layer.setSelected(false);
                    }
                }
            } else {
                //多选选中 把当前序号设置为 size-1 (序号从0开始)
                roomTagLayer.setOrder(roomTagLayers.size() - 1);
            }
        } else {
            //取消选中 把序号大于它的全部减一
            int order = roomTagLayer.getOrder();
            reorder(roomTagLayers, order);
            //把自己的序号重置
            roomTagLayer.setOrder(-1);
        }

        if (selectCallback != null) {
            selectCallback.onSelectChange(roomTagLayer.getAreaInfo(), select);
        }
        refresh();
    }

    /**
     * 设置房间标签选中
     * @param roomList
     */
    public void setSelectRoom(List<Room> roomList) {
        List<YXRoomTagLayer> roomTagLayers = getAreaLayerListByType(YXRoomTagLayer.class);
        if (roomList == null || roomList.size() == 0 || roomTagLayers.size() == 0) {
            return;
        }
        for (int i = 0; i < roomList.size(); i++) {
            Room room = roomList.get(i);
            for (int j = 0; j < roomTagLayers.size(); j++) {
                YXRoomTagLayer yxRoomTagLayer = roomTagLayers.get(j);
                if (yxRoomTagLayer.getAreaInfo().getId() == room.getId()) {
                    yxRoomTagLayer.setSelected(true);
                    break;
                }
            }
        }
        refresh();
    }

    /*移动禁区时 判断是否靠近电源
     */
    public void handleAreaMove(YXAreaLayer areaLayer) {
        if (powerLayer == null || (powerLayer.getArea().x == 0 && powerLayer.getArea().y == 0)) {
            return;
        }
        LogUtils.i("power power: " + powerLayer.getArea().toString());
        if (areaLayer instanceof YXForbiddenAreaLayer) {
            //判断禁区是否与电源保护区域相交
            LogUtils.i("power rect: " + ((YXForbiddenAreaLayer) areaLayer).getArea().toString());
            if (MapUtils.isAreaCrossPower(((YXForbiddenAreaLayer) areaLayer).getArea(), powerLayer.getArea())) {
                if (powerCoveredCallback != null) {
                    powerCoveredCallback.onPowerCovered();
                }
            }
        } else if (areaLayer instanceof YXForbiddenLineLayer) {
            //判断禁过线是否与电源保护区域相交
            LogUtils.i("power line: " + ((YXForbiddenLineLayer) areaLayer).getArea().toString());
            if (MapUtils.isLineCrossPower(((YXForbiddenLineLayer) areaLayer).getArea(), powerLayer.getArea())) {
                if (powerCoveredCallback != null) {
                    powerCoveredCallback.onPowerCovered();
                }
            }
        }
    }

    public void setForbiddenAreaChangeListener(ForbiddenAreaChangeCallback callback) {
        forbiddenAreaChangeCallback = callback;
    }

    public boolean isPowerCovered() {
        if (powerLayer == null || (powerLayer.getArea().x == 0 && powerLayer.getArea().y == 0)) {
            return false;
        }
        return mLayerManager.isPowerCrossForbidArea(powerLayer);
    }

    public boolean isForbiddenAreaChange() {
        return isForbiddenAreaChange;
    }

    public void setForbiddenAreaChange(YXAreaLayer areaLayer) {
        isForbiddenAreaChange = true;
        if (forbiddenAreaChangeCallback != null) {
            forbiddenAreaChangeCallback.onForbiddenAreaChange(areaLayer);
        }
    }

    public void resetForbiddenAreaChangeState() {
        isForbiddenAreaChange = false;
    }

    public YXPowerLayer getPowerLayer() {
        return powerLayer;
    }

    public List<YXForbiddenAreaLayer> getForbiddenAreaLayers() {
        return getAreaLayerListByType(YXForbiddenAreaLayer.class);
    }

    public List<YXForbiddenLineLayer> getForbiddenLineLayers() {
        return getAreaLayerListByType(YXForbiddenLineLayer.class);
    }

    public List<YXForbiddenMopAreaLayer> getForbiddenMopAreaLayers() {
        return getAreaLayerListByType(YXForbiddenMopAreaLayer.class);
    }

    public List<YXCleanAreaLayer> getCleanAreaLayers() {
        List<YXCleanAreaLayer> cleanAreaLayerList = getAreaLayerListByType(YXCleanAreaLayer.class);
        Collections.sort(cleanAreaLayerList, new Comparator<YXCleanAreaLayer>() {
            @Override
            public int compare(YXCleanAreaLayer o1, YXCleanAreaLayer o2) {
                return o1.getOrder() - o2.getOrder();
            }
        });
        return cleanAreaLayerList;
    }

    public List<YXRoomTagLayer> getRoomTagLayers() {
        return getAreaLayerListByType(YXRoomTagLayer.class);
    }

    public void clearRoomTagSeleted() {
        List<YXRoomTagLayer> roomTagLayers = getAreaLayerListByType(YXRoomTagLayer.class);
        for (YXRoomTagLayer roomTagLayer : roomTagLayers) {
            roomTagLayer.setSelected(false);
        }
        refresh();
    }

    public float getBaseScale() {
        return baseScale;
    }

    public Map getMap() {
        return map;
    }

    public boolean hasMap() {
        if (mapLayer == null || mapLayer.getMapBitmap() == null || mapLayer.getMapBitmap().isRecycled()) {
            return false;
        }
        return true;
    }

    public YXAreaDivideLineLayer getAreaDivideLineLayer() {
        return areaDivideLineLayer;
    }

    public List<YXRoomTagLayer> getSelectedRoomTag() {
        List<YXRoomTagLayer> selectedRoom = new ArrayList<>();
        List<YXRoomTagLayer> roomTagLayers = getAreaLayerListByType(YXRoomTagLayer.class);
        for (YXRoomTagLayer layer : roomTagLayers) {
            if (layer.isSelected()) {
                selectedRoom.add(layer);
            }
        }

        Collections.sort(selectedRoom, new Comparator<YXRoomTagLayer>() {
            @Override
            public int compare(YXRoomTagLayer o1, YXRoomTagLayer o2) {
                return o1.getOrder() - o2.getOrder();
            }
        });

        return selectedRoom;
    }

    public YXRoomTagLayer getDivideLineRoom() {
        List<YXRoomTagLayer> selectedRoom = new ArrayList<>();
        List<YXRoomTagLayer> roomTagLayers = getAreaLayerListByType(YXRoomTagLayer.class);
        for (YXRoomTagLayer layer : roomTagLayers) {
            if (layer.isSelected()) {
                selectedRoom.add(layer);
                break;
            }
        }

        if(selectedRoom.size() == 0){
            selectedRoom.add(roomTagLayers.get(0));
        }
        return selectedRoom.get(0);
    }

    @Override
    public void clearMap() {
        super.clearMap();
        tempAreaLayers.clear();
        mapLayer = null;
        pathLayer = null;
        sweeperLayer = null;
        powerLayer = null;
        isUserOperated = false;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (isInEditMode()) {
            return;
        }
        if (hasMap()) {
            super.onDraw(canvas);
        } else {
            canvas.drawColor(this.bgColor);
        }
    }

    public void setZoomLimit(float min, float max) {
        this.min_zoom = min;
        this.max_zoom = max;
    }

    public float getScale() {
        return scale;
    }

    public boolean canSelectRoom() {
        return canSelectRoom;
    }

    public boolean canMultiSelectRoom() {
        return canMultiSelectRoom;
    }

    public boolean isShowRoomOrder() {
        return showRoomOrder;
    }

    public boolean isShowCustom() {
        return showCustom;
    }

    public boolean isShowSuction() {
        return showSuction;
    }

    public boolean isShowWater() {
        return showWater;
    }

    public boolean isShowCleanTimes() {
        return showCleanTimes;
    }

    public float getMinCleanAreaSize() {
        return minCleanAreaSize;
    }

    public void setMinCleanAreaSize(float minCleanAreaSize) {
        this.minCleanAreaSize = minCleanAreaSize;
    }

    public float getPowerProtectAreaSize() {
        return powerProtectAreaSize;
    }

    public void setPowerProtectAreaSize(float powerProtectAreaSize) {
        this.powerProtectAreaSize = powerProtectAreaSize;
        if(powerLayer!=null){
            this.powerLayer.setProtectRadiu(map.getMap().getScreenSize(powerProtectAreaSize));
        }
    }

    public void setRoomSelectCallback(RoomSelectCallback selectCallback) {
        this.selectCallback = selectCallback;
    }

    public void setPowerCoveredCallback(PowerCoveredCallback powerCoveredCallback) {
        this.powerCoveredCallback = powerCoveredCallback;
    }

    public void setCanRotateCleanArea(boolean canRotateCleanArea) {
        this.canRotateCleanArea = canRotateCleanArea;
    }

    public interface RoomSelectCallback {
        void onSelectChange(Room room, boolean select);
    }

    public interface ForbiddenAreaChangeCallback {
        //改变类型 后续可能会加 预留
        int TYPE_DELETE = 0;
        int TYPE_ADD = 1;
        int TYPE_MOVE = 2;
        int TYPE_ROTATE = 3;
        int TYPE_SCALE = 4;

        void onForbiddenAreaChange(YXAreaLayer areaLayer);
    }
}
